Imports System.IO
Imports System.Xml.Serialization
Module SimpleIndexer
    Private XmlDoc As New Xml.XmlDocument
    Private Players() As String
    Private PlayersCount As Integer = 0

    Private Const Top_N_Count As Integer = 20
    Private Const Latest_N_Days As Integer = 30

    Private boss() As String = Nothing

    Private Classes() As String = {"dk", "drd", "hnt", "mag", "pal", "pri", "rog", "sha", "war", "wrl", "ukw"}
    Private Classes2() As String = {"Death Knight", "Druid", "Hunter", "Mage", "Paladin", "Priest", "Rogue", "Shaman", "Warrior", "Warlock", "Unknown"}

    Private Zones() As String = { _
        "coliseum", "ulduar", "eyeofeternity", "naxxramas", "obsidiansanctum", "archavon", _
        "sunwell", "blacktemple", "hyjalsummit", "tempestkeep", "serpentshrine", "Magtheridon", "gruul", "zulaman", "karazhan", _
        "unknown" _
    }
    Private Zones2() As String = { _
        "ToC", "Uld", "EoE", "Naxx", "OS", "VoA", _
        "SWP", "BT", "MH", "TK", "SSC", "ML", "GL", "ZA", "Kara", _
        "??" _
    }

    Private RemoveDescriptionsDateSpan As Integer = 0
    Private RemoveFullDateSpan As Integer = 60
    Private ArmoryInterval As Integer = 10

    Private TargetPath As String = ""
    Private CharaInfo As New WowCrawler.CharactersInfo
    Private ItemDB As WowCrawler.ItemDB
    'Private EnchantDB As WowCrawler.EnchantDB

    Private CrawlGuild As String = ""

    Private Structure BossCombat
        <XmlAttribute()> Dim BossName As String
        <XmlAttribute()> Dim Count As Integer
        <XmlAttribute()> Dim AveDps As Single
        <XmlAttribute()> Dim AveHps As Single
        <XmlAttribute()> Dim AveDispel As Single

        <XmlAttribute()> Dim DpsRankCount As Integer
        <XmlAttribute()> Dim HealRankCount As Integer
        <XmlAttribute()> Dim AveDpsRank As Single
        <XmlAttribute()> Dim AveHealRank As Single
    End Structure

    Private Structure PlayerInfo
        <XmlAttribute()> Dim Name As String
        <XmlAttribute()> Dim ClassName As String
        <XmlAttribute()> Dim Guild As String

        <XmlAttribute()> Dim AveDpsRank As Double
        <XmlAttribute()> Dim AveDpsCount As Integer
        <XmlAttribute()> Dim TopDpsCount As Integer

        <XmlAttribute()> Dim AveHealRank As Double
        <XmlAttribute()> Dim AveHealCount As Integer
        <XmlAttribute()> Dim TopHealCount As Integer

        <XmlAttribute()> Dim AveDead As Double
        <XmlAttribute()> Dim AveDeadCount As Integer

        <XmlAttribute()> Dim AveDispel As Double
        <XmlAttribute()> Dim AveDispelCount As Integer

        <XmlAttribute()> Dim LastJoin As Date
        <XmlAttribute()> Dim BossCombatInfo() As BossCombat
    End Structure
    Private PlayersInfo() As PlayerInfo

    Public Structure GuildCounter
        Dim Name As String
        Dim Count As Integer
    End Structure

    Dim GuildList() As GuildCounter = Nothing
    Dim GuildCount As Integer = 0
    Dim BiggestGuildName As String = ""


    Sub Main(ByVal Arguments() As String)
        Dim i As Integer

        TargetPath = My.Computer.FileSystem.CurrentDirectory

        For i = 0 To Arguments.Length - 1
            If Mid(Arguments(i), 1, 1) = "/" Then
                Mid(Arguments(i), 1, 1) = "-"
                Arguments(i) = LCase(Arguments(i))
            End If

            Select Case Arguments(i)
                Case "-h"
                    '--- help
                    help()
                    Exit Sub
                Case "-rd"
                    '--- remove descriptions
                    Try
                        RemoveDescriptionsDateSpan = CInt(Arguments(i + 1))
                    Catch ex As Exception
                        help()
                        Exit Sub
                    End Try
                Case "-rf"
                    '--- remove descriptions
                    Try
                        RemoveFullDateSpan = CInt(Arguments(i + 1))
                    Catch ex As Exception
                        help()
                        Exit Sub
                    End Try
                Case "-realm"
                    '--- remove descriptions
                    Try
                        CharaInfo.Realm = Arguments(i + 1)
                    Catch ex As Exception
                        help()
                        Exit Sub
                    End Try
                Case "-region"
                    '--- remove descriptions
                    Try
                        CharaInfo.Region = Arguments(i + 1)
                    Catch ex As Exception
                        help()
                        Exit Sub
                    End Try
                Case "-interval"
                    '--- remove descriptions
                    Try
                        CharaInfo.UpdateInterval = CInt(Arguments(i + 1))
                    Catch ex As Exception
                        help()
                        Exit Sub
                    End Try
                Case "-guild"
                    '--- remove descriptions
                    Try
                        CrawlGuild = Arguments(i + 1)
                    Catch ex As Exception
                        help()
                        Exit Sub
                    End Try
                Case "-p"
                    '--- remove descriptions
                    Try
                        TargetPath = Arguments(i + 1)
                    Catch ex As Exception
                        help()
                        Exit Sub
                    End Try
            End Select
        Next

        Try
            XmlDoc.Load(My.Computer.FileSystem.CombinePath(TargetPath, "data.xml"))
        Catch ex As Exception
            Exit Sub
        End Try
        ReDim Players(0)

        '--- xml update
        CreateList()
        CreateGuildList()
        EachRaidRanking()

        '--- crawl armory
        If CrawlGuild <> "" Then
            CharaInfo.GetGuildMembersInfo(CrawlGuild)
            CharaInfo.SaveArmoryData()
        End If

        Dim ct As Integer = 0
        For i = 0 To PlayersCount - 1
            If Joined(i, ArmoryInterval) Then
                CharaInfo.GetCharactersInfo(Players(i))
                ct += 1
                If ct Mod 10 = 0 Then
                    CharaInfo.SaveArmoryData()
                End If
            End If
        Next
        CharaInfo.UpdateInterval = 365 * 100 '--- no update 100 years

        '--- html update
        CreateHeaderHtml()
        CreateRaidHtml("history_raid.html", "comment")
        CreateRaidHtml("history_raid2.html", "start")
        CreatePlayerHtml()
        CreateMenuHtml()
        CreateTop10Html()
        CreateTopAve10Html()

        '        compress()
        RemoveFiles()

        'Try
        '    XmlDoc.Save(My.Computer.FileSystem.CombinePath(TargetPath,"data2.xml"))
        'Catch ex As Exception
        '    Exit Sub
        'End Try

    End Sub

    Private Sub help()
        Dim msg As String = ""

        msg &= "[Switches]" & vbCrLf
        msg &= "-p path" & vbCrLf
        msg &= vbTab & "Path of the target folder what has data.xml" & vbCrLf
        msg &= "-rf N" & vbCrLf
        msg &= vbTab & "N - latest days, default=0" & vbCrLf
        msg &= vbTab & "remove almost full files excl index.html and data.xml" & vbCrLf
        msg &= "-rd N" & vbCrLf
        msg &= vbTab & "N - latest days, default=30" & vbCrLf
        msg &= vbTab & "remove description files for spells, mobs and scripts" & vbCrLf
        msg &= "-region US|EN" & vbCrLf
        msg &= vbTab & "Region information to access Armory" & vbCrLf
        msg &= "-realm R" & vbCrLf
        msg &= vbTab & "Realm name to access Armory" & vbCrLf
        msg &= "-interval I" & vbCrLf
        msg &= vbTab & "Interval days to re-access Armory" & vbCrLf
        msg &= "-guild G" & vbCrLf
        msg &= vbTab & "Guild name to pre-fetch characters information from Armory" & vbCrLf
        msg &= "-h" & vbCrLf
        msg &= vbTab & "Show help message" & vbCrLf

        System.Console.Error.WriteLine(msg)
        MsgBox(msg)
    End Sub

    Private Function Joined(ByVal pno As Long, ByVal interval As Integer) As Boolean
        Dim j As Boolean = False

        If (Now - PlayersInfo(pno).LastJoin).Days <= interval Then
            Return True
        Else
            Return False
        End If
    End Function

    Private Sub CreateList()
        Dim node As Xml.XmlElement
        Dim i As Integer

        Dim raiddate As Date

        Dim BossDB As New RaidBossList
        Dim bossName As String = ""

        For Each node In XmlDoc.SelectNodes("wws-history/raid")
            Try
                bossName = node.Attributes("comment").Value
            Catch ex As Exception
                bossName = "unknown"
            End Try

            If boss Is Nothing Then
                ReDim boss(0)
                boss(0) = bossName
            Else
                Dim exist As Boolean = False
                For i = 0 To boss.Length - 1
                    If boss(i) = bossName Then
                        exist = True
                        Exit For
                    End If
                Next
                If Not exist Then
                    ReDim Preserve boss(boss.Length)
                    boss(boss.Length - 1) = bossName
                End If
            End If

            If BossDB.GetAreaName(bossName) = "" Then
                For i = 0 To Zones.Length - 1
                    If node.Attributes("zone").Value = Zones(i) Then
                        node.Attributes("zone").Value = Zones2(i)
                    End If
                Next
            Else
                node.Attributes("zone").Value = BossDB.GetAreaName(bossName)
            End If

            Dim attr As Xml.XmlAttribute
            raiddate = CalculateDate(node.Attributes("start").Value)

            'attr = XmlDoc.CreateAttribute("raid_month")
            'attr.Value = Format(raiddate, "MM/yyyy")
            'node.SetAttributeNode(attr)

            'attr = XmlDoc.CreateAttribute("raid_date")
            'attr.Value = Format(raiddate, "MM-dd-yyyy")
            'node.SetAttributeNode(attr)

            attr = XmlDoc.CreateAttribute("latestNdays")
            If (Today - raiddate).Days <= Latest_N_Days Then
                attr.Value = "1"
            Else
                attr.Value = "0"
            End If
            node.SetAttributeNode(attr)
        Next

        Dim compare As New BossCompare
        Array.Sort(boss, compare)

        '--- update players list
        PlayersCount = 0
        Dim pct As Integer = 0
        For Each node In XmlDoc.SelectNodes("wws-history/raid/player")
            Dim ex As Boolean = False

            If PlayersCount = 0 Then
                ex = False
                pct = 0
            Else
                For i = 0 To PlayersCount - 1
                    If Players(i) = node.Attributes("name").Value Then
                        ex = True
                        pct = i
                        Exit For
                    End If
                Next
            End If

            If ex Then
                raiddate = CalculateDate(node.ParentNode.Attributes("start").Value)
                If PlayersInfo(pct).LastJoin < raiddate Then
                    PlayersInfo(pct).LastJoin = raiddate
                End If
            Else
                ReDim Preserve Players(PlayersCount)
                Players(PlayersCount) = node.Attributes("name").Value


                ReDim Preserve PlayersInfo(PlayersCount)

                PlayersInfo(PlayersCount) = New PlayerInfo
                PlayersInfo(PlayersCount).Name = Players(PlayersCount)

                ReDim PlayersInfo(PlayersCount).BossCombatInfo(boss.Length - 1)

                Try
                    PlayersInfo(PlayersCount).ClassName = node.Attributes("clsname").Value
                Catch e As Exception
                    For i = 0 To Classes.Length - 1
                        If Classes(i) = node.Attributes("classe").Value Then
                            Classes2(i) = node.Attributes("classe").Value
                            Exit For
                        End If
                    Next
                End Try

                PlayersInfo(PlayersCount).Guild = CharaInfo.GetCharactersInfo(PlayersInfo(PlayersCount).Name).Guild

                PlayersInfo(PlayersCount).AveHealRank = 0
                PlayersInfo(PlayersCount).AveHealCount = 0
                PlayersInfo(PlayersCount).TopHealCount = 0

                PlayersInfo(PlayersCount).AveDpsRank = 0
                PlayersInfo(PlayersCount).AveDpsCount = 0
                PlayersInfo(PlayersCount).TopDpsCount = 0

                PlayersInfo(PlayersCount).AveDead = 0
                PlayersInfo(PlayersCount).AveDeadCount = 0

                PlayersInfo(PlayersCount).AveDispel = 0
                PlayersInfo(PlayersCount).AveDispelCount = 0

                PlayersInfo(PlayersCount).LastJoin = CalculateDate(node.ParentNode.Attributes("start").Value)

                PlayersCount += 1
            End If
        Next
    End Sub

    Private Sub CreateGuildList()
        Dim chdata As WowCrawler.CharactersInfo.Characters = Nothing

        Dim i As Integer
        Dim p As Integer

        '--- Guild List
        For p = 0 To PlayersCount - 1
            chdata = CharaInfo.GetCharactersInfo(Players(p))
            If chdata.Guild <> "" Then
                If GuildCount = 0 Then
                    ReDim Preserve GuildList(GuildCount)
                    GuildList(GuildCount) = New GuildCounter
                    GuildList(GuildCount).Name = chdata.Guild
                    GuildList(GuildCount).Count = 1
                    GuildCount += 1
                Else
                    Dim Found As Boolean = False
                    For i = 0 To GuildCount - 1
                        If GuildList(i).Name = chdata.Guild Then
                            If chdata.Guild <> "" Then
                                GuildList(i).Count += 1
                            End If
                            Found = True
                            Exit For
                        End If
                    Next
                    If Not Found Then
                        ReDim Preserve GuildList(GuildCount)
                        GuildList(GuildCount) = New GuildCounter
                        GuildList(GuildCount).Name = chdata.Guild
                        GuildList(GuildCount).Count = 1
                        GuildCount += 1
                    End If
                End If
            End If
        Next

        '--- Biggest Guild
        Dim Max As Integer = -1

        For i = 0 To GuildCount - 1
            If GuildList(i).Count > Max Then
                Max = GuildList(i).Count
                BiggestGuildName = GuildList(i).Name
            End If
        Next
    End Sub

    Private Sub compress()
        Dim node As Xml.XmlElement = Nothing

        For Each node In XmlDoc.SelectNodes("wws-history/raid")
            Dim dir As String = ""

            Try
                dir = node.Attributes("dir").Value
            Catch ex As Exception

            End Try

            If dir <> "" Then
                Dim cmd As String
                cmd = """C:\Program Files\WinRAR\rar"" a -m5 -o- " & "..\" & dir & " " & "..\" & dir
                Shell(cmd, AppWinStyle.Hide, False, -1)
            End If
        Next
    End Sub

    Private Sub CreateHeaderHtml()
        Dim html As String = ""
        '--- frame
        html = ""
        html = "<frameset cols=""150,*""><frame name=""menu"" src=""menu.html""><frame name=""main"" src=""readme.html""></frameset>"

        Try
            FileOpen(1, My.Computer.FileSystem.CombinePath(TargetPath, "index.html"), OpenMode.Output)
            Print(1, html)
        Catch ex As Exception

        End Try
        FileClose(1)

        '--- read me
        html = GetHtmlHeader("Raid Report by StasisCL")

        html &= "<h2 onclick=expand('dontbuygold')>Don't Buy Gold!! (@_@!!</h2>" & vbCrLf
        html &= "<UL id=dontbuygold><li/>Or Die!</UL>" & vbCrLf & vbCrLf

        html &= "<h2 onclick=expand('feature')>Features</h2>" & vbCrLf
        html &= "<div id=feature>" & vbCrLf
        html &= "<ul>" & vbCrLf
        html &= "<li/><a href=""http://code.google.com/p/stasiscl/"">StasisCL</a> static report, but spells and ennemies data are removed" & vbCrLf
        html &= "<li/>Indexing for Raid <a href=""history_raid2.html"">by Date</a> and <a href=""history_raid.html"">by Boss</a>" & vbCrLf
        html &= "<li/>Indexing for each player by Boss" & vbCrLf
        html &= "<li/><a href=""top10.html"">Top " & Top_N_Count & "</a> DPS or Healing for each boss" & vbCrLf
        html &= "<li/><a href=""topave.html"">Top " & Top_N_Count & "</a> Dispel during recent 30 days" & vbCrLf
        html &= "<li/>Talent (from Armory)" & vbCrLf
        html &= "</ul>" & vbCrLf
        html &= "</div>" & vbCrLf & vbCrLf

        html &= "<h2 onclick=expand('pinfo')>Product Info</h2>" & vbCrLf
        html &= "<div id=pinfo>" & vbCrLf
        html &= "<ul>" & vbCrLf
        html &= "<li/>Base Data were created by <a href=""http://code.google.com/p/stasiscl/"">StasisCL</a> by gianmerlino<br/>" & vbCrLf
        html &= "<li/>Legend Data were created by " & My.Application.Info.ProductName & " ver. " & My.Application.Info.Version.Major & "." & My.Application.Info.Version.Minor & " by " & My.Application.Info.CompanyName & vbCrLf
        html &= "</ul>" & vbCrLf
        html &= "</div>" & vbCrLf & vbCrLf

        html &= "<h2 onclick=expand('updates')>Updates</h2>" & vbCrLf
        html &= "<div id=updates>" & vbCrLf
        html &= "<ul>" & vbCrLf
        html &= "<li/>Ver1.7 (Sep 17, 2009)" & vbCrLf
        html &= "  <ul>" & vbCrLf
        html &= "  <li/>Healing results include Guess-absorption." & vbCrLf
        html &= "  <li/>Collapse/Expand each block." & vbCrLf
        html &= "  <li/>Glyphs and Achievements are also crawled." & vbCrLf
        html &= "  </ul>" & vbCrLf
        html &= "<li/>Ver1.6 (Aug 27, 2009)" & vbCrLf
        html &= "  <ul>" & vbCrLf
        html &= "  <li/>Main Guild of the raid is shown." & vbCrLf
        html &= "  <li/>Suggest for deleted, renamed, or transfered character," & vbCrLf
        html &= "  </ul>" & vbCrLf
        html &= "<li/>Ver1.5 (May 19, 2009)" & vbCrLf
        html &= "  <ul>" & vbCrLf
        html &= "  <li/>Average DPS and HPS for each boss are calculated," & vbCrLf
        html &= "  <li/>Average DPS rank and HPS rank for each boss are calculated," & vbCrLf
        html &= "  <li/>Characters Stars (health, mana, str, agi, etc.) are also shown." & vbCrLf
        html &= "  <li/>A chacacter no longer stays when he left a guild." & vbCrLf
        html &= "  </ul>" & vbCrLf
        html &= "</ul>" & vbCrLf
        html &= "</div>" & vbCrLf & vbCrLf

        html &= "</body></html>"
        Try
            FileOpen(1, My.Computer.FileSystem.CombinePath(TargetPath, "readme.html"), OpenMode.Output)
            Print(1, html)
        Catch ex As Exception

        End Try
        FileClose(1)
    End Sub

    Private Sub CreateRaidHtml(ByVal HtmlFilename As String, ByVal sortkey As String)
        Dim node As Xml.XmlElement = Nothing
        Dim keys() As String = Nothing
        Dim k As Integer

        Dim maxdps As Double = 0
        Dim maxhps As Double = 0

        Dim dps As Double
        Dim hps As Double
        '--- sort keys
        For Each node In XmlDoc.SelectNodes("wws-history/raid")
            If keys Is Nothing Then
                ReDim keys(0)
                keys(0) = node.Attributes(sortkey).Value
            Else
                Dim exist As Boolean = False
                For k = 0 To keys.Length - 1
                    If keys(k) = node.Attributes(sortkey).Value Then
                        exist = True
                        Exit For
                    End If
                Next

                If Not exist Then
                    ReDim Preserve keys(keys.Length)
                    keys(keys.Length - 1) = node.Attributes(sortkey).Value
                End If
            End If

            Try
                dps = node.Attributes("dmg").Value / node.Attributes("lg").Value * 60 * 1000
            Catch ex As Exception
                dps = 0
            End Try
            If dps > maxdps Then
                maxdps = dps
            End If

            Try
                hps = node.Attributes("effheal").Value / node.Attributes("lg").Value * 60 * 1000
            Catch ex As Exception
                hps = 0
            End Try
            If hps > maxhps Then
                maxhps = hps
            End If
        Next

        If keys IsNot Nothing Then
            Dim cstrdes As New CompareStringDescend
            Select Case sortkey
                Case "comment"
                    Dim compare As New BossCompare
                    Array.Sort(keys, compare)
                Case "start"
                    Array.Sort(keys, cstrdes)
                Case Else
                    Array.Sort(keys)
            End Select
        End If

        Dim html As String = ""

        Select Case sortkey
            Case "comment"
                html = GetHtmlHeader("Raid Report / Boss")
            Case "start"
                html = GetHtmlHeader("Raid Report / Date")
            Case Else
                html = GetHtmlHeader("Raid Report")
        End Select
        html &= "<P>Updated: " & Format(Today(), "MM-dd-yyyy") & ", DON'T BUY GOLD!</P>"

        Dim tableheader As String = ""
        Select Case sortkey
            Case "comment"
                tableheader = "<tr><th>Date</th><th>Time (sec)</th><th colspan=2>Raid DPS</th><th colspan=2>Raid EffHPS</th><th>Over Heal</th></tr>" & vbCrLf
            Case "start"
                tableheader = "<tr><th>Attempt</th><th>Zone</th><th>Time (sec)</th><th colspan=2>Raid DPS</th><th colspan=2>Raid EffHPS</th><th>Over Heal</th></tr>" & vbCrLf
        End Select

        Dim table As String = ""
        Dim firsttable As Boolean = True

        If keys IsNot Nothing Then

            For k = 0 To keys.Length - 1
                For Each node In XmlDoc.SelectNodes("wws-history/raid")
                    If node.Attributes(sortkey).Value = keys(k) Then
                        Select Case sortkey
                            Case "comment" '---
                                If table <> node.Attributes("comment").Value Then
                                    table = node.Attributes("comment").Value
                                    If Not firsttable Then
                                        html &= "</table>" & vbCrLf
                                        html &= "</div>" & vbCrLf
                                    End If
                                    html &= vbCrLf
                                    html &= "<h2 onclick=expand('key" & k & "')>" & node.Attributes("comment").Value & "/" & node.Attributes("zone").Value & "</h2>" & vbCrLf
                                    html &= "<div id=key" & k & ">" & vbCrLf

                                    html &= "<table border>" & vbCrLf
                                    html &= tableheader
                                    firsttable = False
                                End If
                            Case "start" '---
                                If table <> GetDate(node.Attributes("start").Value) Then
                                    table = GetDate(node.Attributes("start").Value)
                                    If Not firsttable Then
                                        html &= "</table>" & vbCrLf
                                        html &= "</div>" & vbCrLf
                                    End If
                                    html &= vbCrLf
                                    html &= "<h2 onclick=expand('key" & k & "')>" & GetDate(node.Attributes("start").Value) & "</h2>" & vbCrLf
                                    html &= "<div id=key" & k & ">" & vbCrLf
                                    html &= "<table border>" & vbCrLf
                                    html &= tableheader
                                    firsttable = False
                                End If
                            Case Else
                        End Select

                        html &= "<tr>" & vbCrLf

                        If sortkey <> "start" Then
                            If My.Computer.FileSystem.FileExists("..\" & node.Attributes("dir").Value & "\index.html") Then
                                html &= vbTab & "<td><a href=""../" & node.Attributes("dir").Value & "/index.html#top"">" & GetDate(node.Attributes("start").Value) & "</a>" & "</td>" & vbCrLf
                            Else
                                html &= vbTab & "<td>" & GetDate(node.Attributes("start").Value) & "</td>" & vbCrLf
                            End If
                        End If

                        If sortkey <> "comment" Then
                            If My.Computer.FileSystem.FileExists("..\" & node.Attributes("dir").Value & "\index.html") Then
                                html &= vbTab & "<td><a href=""../" & node.Attributes("dir").Value & "/index.html#top"">" & node.Attributes("comment").Value & "</a>" & "</td>" & vbCrLf
                            Else
                                html &= vbTab & "<td><nobr>" & node.Attributes("comment").Value & "</nobr></td>" & vbCrLf
                            End If

                            If node.Attributes("zone").Value <> "" Then
                                html &= vbTab & "<td>" & node.Attributes("zone").Value & "</td>" & vbCrLf
                            Else
                                html &= vbTab & "<td>&nbsp;</td>" & vbCrLf
                            End If
                        End If

                        html &= vbTab & "<td align=right>" & Format(node.Attributes("lg").Value / (60 * 1000), "###,###,##0.0") & "</td>" & vbCrLf

                        Dim percent As Double

                        '--- dps
                        Try
                            dps = node.Attributes("dmg").Value / node.Attributes("lg").Value * 60 * 1000
                        Catch ex As Exception
                            dps = 0
                        End Try
                        Try
                            percent = Math.Round(dps / maxdps * 100, 0)
                        Catch ex As Exception
                            percent = 0
                        End Try
                        html &= GetBar(percent, "red")
                        html &= vbTab & "<td align=right>" & Format(dps, "###,###,##0.0") & "</td>" & vbCrLf

                        '--- hps
                        Try
                            hps = node.Attributes("effheal").Value / node.Attributes("lg").Value * 60 * 1000
                        Catch ex As Exception
                            hps = 0
                        End Try
                        Try
                            percent = hps / maxhps * 100
                        Catch ex As Exception
                            percent = 0
                        End Try
                        html &= GetBar(percent, "blue")
                        html &= vbTab & "<td align=right>" & Format(hps, "###,###,##0.0") & "</td>" & vbCrLf

                        '--- over heal
                        Try
                            If CDbl("0" & node.Attributes("totheal").Value) = 0.0 Then
                                html &= vbTab & "<td align=right>-.-%</td>" & vbCrLf
                            Else
                                html &= vbTab & "<td align=right>" & Format((1.0 - node.Attributes("effheal").Value / node.Attributes("totheal").Value) * 100.0, "##0.0") & "%</td>" & vbCrLf
                            End If
                        Catch ex As Exception
                            html &= vbTab & "<td>&nbsp;</td>" & vbCrLf
                        End Try

                        html &= "</tr>" & vbCrLf
                    End If
                Next
            Next
        End If

        html &= "</table>" & vbCrLf
        html &= "</div>" & vbCrLf

        html &= "<p><a href=""data.xml"">The raw data</a> is xml. If you have Excel 2003 or later, you can open the raw data file then calculate.</p>" & vbCrLf
        html &= "</body>" & vbCrLf
        html &= "</html>" & vbCrLf

        Try
            FileOpen(1, My.Computer.FileSystem.CombinePath(TargetPath, HtmlFilename), OpenMode.Output)
            Print(1, html)
        Catch ex As Exception

        End Try
        FileClose(1)
    End Sub

    Private Function CalculateDate(ByVal DateValue As Long) As Date
        Dim CalDate As Date = "1970/1/1 00:00:00.000"

        CalDate = CalDate.AddTicks(DateValue * 10000)
        CalDate = CalDate.ToLocalTime

        CalDate = CalDate.AddHours(-4.5)

        Return CalDate
    End Function

    Private Function GetDate(ByVal DateValue As Long) As String
        Return Format(CalculateDate(DateValue), "MM-dd-yyyy")
    End Function


    Private Sub CreatePlayerHtml()
        Dim chdata As WowCrawler.CharactersInfo.Characters = Nothing

        Dim node As Xml.XmlElement

        Dim i As Integer
        Dim p As Integer

        '---
        Array.Sort(Players)

        Dim title As String

        Dim html As String = ""
        For p = 0 To PlayersCount - 1
            chdata = CharaInfo.GetCharactersInfo(Players(p))

            title = Players(p)

            If chdata.Guild <> "" Then
                title &= " / " & chdata.Guild
            End If

            html = GetHtmlHeader(title)
            'html &= "<P>Updated: " & Format(Today(), "MM-dd-yyyy") & ", DON'T BUY GOLD!</P>" & vbCrLf

            Dim CIV As New WowCrawler.CharaInfoViewer
            html &= CIV.CharaInfoToHtml(chdata)

            For i = 0 To PlayersCount - 1
                If Players(p) = PlayersInfo(i).Name Then
                    html &= vbCrLf
                    html &= "<h2 onclick=expand('averages')>Average Values during recent " & Latest_N_Days & " days</h2>" & vbCrLf
                    html &= "<div id=averages>" & vbCrLf
                    html &= "<table border width=80%>" & vbCrLf
                    html &= "<tr><th>DPS rank</th><th>Heal Rank</th><th>Dispel Count</th><th>Death Count</th></tr>" & vbCrLf
                    html &= "<tr>" & vbCrLf
                    html &= "<td align=center>" & Format(PlayersInfo(i).AveDpsRank, "#,##0.00") & " / " & PlayersInfo(i).AveDpsCount & "</td>" & vbCrLf
                    html &= "<td align=center>" & Format(PlayersInfo(i).AveHealRank, "#,##0.00") & " / " & PlayersInfo(i).AveHealCount & "</td>" & vbCrLf
                    html &= "<td align=center>" & Format(PlayersInfo(i).AveDispel, "#,##0.000") & " / " & PlayersInfo(i).AveDispelCount & "</td>" & vbCrLf
                    html &= "<td align=center>" & Format(PlayersInfo(i).AveDead, "#,##0.000") & " / " & PlayersInfo(i).AveDeadCount & "</td>" & vbCrLf
                    html &= "</tr>" & vbCrLf
                    html &= "</table>" & vbCrLf
                    html &= "</div>" & vbCrLf
                    Exit For
                End If
            Next

            Dim dps As Double = 0
            Dim hps As Double = 0
            Dim maxdps As Double = 0
            Dim maxhps As Double = 0

            Dim b As Integer
            For b = 0 To boss.Length - 1
                maxdps = 0
                maxhps = 0

                Dim zone = ""
                For Each node In XmlDoc.SelectNodes("wws-history/raid/player[@name=""" & Players(p) & """]")
                    If boss(b) = node.ParentNode.Attributes("comment").Value Then
                        '--- zone
                        If node.ParentNode.Attributes("zone").Value <> "" Then
                            zone = "/" & node.ParentNode.Attributes("zone").Value
                        Else
                            zone = ""
                        End If

                        Try
                            dps = node.Attributes("dmg").Value / node.ParentNode.Attributes("lg").Value * 60 * 1000
                        Catch ex As Exception
                            dps = CDbl("0" & node.Attributes("dps").Value)
                        End Try
                        If maxdps < dps Then
                            maxdps = dps
                        End If

                        Try
                            hps = node.Attributes("effheal").Value / node.ParentNode.Attributes("lg").Value * 60 * 1000
                        Catch ex As Exception
                            hps = CDbl("0" & node.Attributes("heal").Value)
                        End Try
                        If maxhps < hps Then
                            maxhps = hps
                        End If
                    End If
                Next

                'Dim boss As String = ""
                'Dim bossattr As String = ""

                Dim ct As Integer = 0

                For Each node In XmlDoc.SelectNodes("wws-history/raid[@comment=""" & boss(b) & """]/player[@name=""" & Players(p) & """]")
                    If ct = 0 Then
                        html &= vbCrLf
                        html &= "<h2 onclick=expand('boss" & b & "')>" & boss(b) & zone & "</h2>" & vbCrLf
                        html &= "<div id=boss" & b & ">" & vbCrLf

                        '--- ave dps, hps, dispel
                        Dim pidx As Integer
                        For pidx = 0 To PlayersInfo.Length - 1
                            If PlayersInfo(pidx).Name = Players(p) Then
                                Exit For
                            End If
                        Next
                        html &= "<P>" & vbCrLf
                        html &= "Average DPS: " & Format(PlayersInfo(pidx).BossCombatInfo(b).AveDps, "###,##0.0")
                        If PlayersInfo(pidx).BossCombatInfo(b).DpsRankCount > 0 Then
                            html &= " , Rank:" & Format(PlayersInfo(pidx).BossCombatInfo(b).AveDpsRank, "###,##0.0") & " (" & PlayersInfo(pidx).BossCombatInfo(b).DpsRankCount & ")"
                        End If

                        html &= "/ HPS: " & Format(PlayersInfo(pidx).BossCombatInfo(b).AveHps, "###,##0.0")
                        If PlayersInfo(pidx).BossCombatInfo(b).HealRankCount > 0 Then
                            html &= " , Rank:" & Format(PlayersInfo(pidx).BossCombatInfo(b).AveHealRank, "###,##0.0") & " (" & PlayersInfo(pidx).BossCombatInfo(b).HealRankCount & ")"
                        End If

                        If PlayersInfo(pidx).BossCombatInfo(b).AveDispel > 0 Then
                            html &= "/ Dispel: " & Format(PlayersInfo(pidx).BossCombatInfo(b).AveDispel, "###,##0.0")
                        End If
                        html &= "<P>" & vbCrLf

                        html &= "<table border>" & vbCrLf
                        html &= "<tr><th>Date</th><th colspan=3>DPS</th><th colspan=3>EffHPS</th><th>Over Heal</th><th>Dispel</th><th>Death</th></tr>" & vbCrLf

                        ct = +1
                    End If

                    html &= "<tr>" & vbCrLf

                    If My.Computer.FileSystem.FileExists("..\" & node.ParentNode.Attributes("dir").Value & "\index.html") Then
                        html &= vbTab & "<td><a href=""../" & node.ParentNode.Attributes("dir").Value & "/index.html#top"">" & GetDate(node.ParentNode.Attributes("start").Value) & "</a>" & "</td>" & vbCrLf
                    Else
                        html &= vbTab & "<td>" & GetDate(node.ParentNode.Attributes("start").Value) & "</td>" & vbCrLf
                    End If

                    Dim percent As Double = 0

                    Try
                        dps = node.Attributes("dmg").Value / node.ParentNode.Attributes("lg").Value * 60 * 1000
                    Catch ex As Exception
                        dps = CDbl("0" & node.Attributes("dps").Value)
                    End Try
                    Try
                        percent = Math.Round(dps / maxdps * 100, 0)
                    Catch ex As Exception
                        percent = 0
                    End Try
                    html &= vbTab & GetBar(percent, "red")
                    html &= vbTab & "<td align=right>" & Format(dps, "###,###,##0.0") & "</td>" & vbCrLf
                    html &= vbTab & "<td aligh=center>" & getCount(node.Attributes("dpsrank").Value) & "</td>" & vbCrLf

                    '--- hps
                    Try
                        hps = node.Attributes("effheal").Value / node.ParentNode.Attributes("lg").Value * 60 * 1000
                    Catch ex As Exception
                        hps = CDbl("0" & node.Attributes("heal").Value)
                    End Try
                    Try
                        percent = hps / maxhps * 100
                    Catch ex As Exception
                        percent = 0
                    End Try
                    html &= vbTab & GetBar(percent, "blue")
                    html &= vbTab & "<td align=right>" & Format(hps, "###,###,##0.0") & "</td>" & vbCrLf
                    html &= vbTab & "<td aligh=center>" & getCount(node.Attributes("healrank").Value) & "</td>" & vbCrLf

                    Try
                        If CDbl("0" & node.Attributes("totheal").Value) = 0.0 Then
                            html &= vbTab & "<td align=right>-.-%</td>" & vbCrLf
                        Else
                            html &= vbTab & "<td align=right>" & Format((1.0 - node.Attributes("effheal").Value / node.Attributes("totheal").Value) * 100.0, "#,##0.0") & "%</td>" & vbCrLf
                        End If
                    Catch ex As Exception
                        html &= vbTab & "<td align=right>" & Format(CDbl(node.Attributes("ovh").Value), "##0.0") & "%</td>" & vbCrLf
                    End Try

                    '--- dispel
                    Try
                        html &= vbTab & "<td align=right>" & Format(CInt(node.Attributes("decurse").Value), "##0") & "</td>" & vbCrLf
                    Catch ex As Exception
                        html &= vbTab & "<td align=right>-</td>" & vbCrLf
                    End Try

                    '--- death
                    Try
                        html &= vbTab & "<td align=right>" & Format(CInt(node.Attributes("death").Value), "##0") & "</td>" & vbCrLf
                    Catch ex As Exception
                        html &= vbTab & "<td align=right>-</td>" & vbCrLf
                    End Try

                    html &= "</tr>" & vbCrLf
                Next

                If ct > 0 Then
                    html &= "</table>" & vbCrLf
                    html &= "</div>" & vbCrLf
                End If
            Next

            html &= "</body>" & vbCrLf
            html &= "</html>" & vbCrLf

            Try
                FileOpen(1, My.Computer.FileSystem.CombinePath(TargetPath, "history_p" & p & ".html"), OpenMode.Output)
                Print(1, html)
            Catch ex As Exception

            End Try
            FileClose(1)
        Next
    End Sub

    Private Sub CreateMenuHtml()
        Dim html As String
        Dim cl As Integer
        Dim p As Integer

        Dim gld As Integer
        Dim guild As String

        html = GetHtmlHeader("")

        html &= "<nobr><a href=""history_raid2.html"" target=main>Raid / Date</A></nobr><br/>" & vbCrLf
        html &= "<nobr><a href=""history_raid.html"" target=main>Raid / Boss</A></nobr><br/>" & vbCrLf
        html &= "<hr/>" & vbCrLf

        html &= "<nobr><a href=""top10.html"" target=main>Top " & Top_N_Count & "</A></nobr><br/>" & vbCrLf
        html &= "<nobr><a href=""topave.html"" target=main>Misc Info</A></nobr><br/>" & vbCrLf
        html &= "<hr/>" & vbCrLf

        html &= "<table width=100%>" & vbCrLf
        For gld = 0 To 1
            If gld = 0 Then
                If BiggestGuildName = "" Then
                    html &= "<tr><td width=100%><nobr>[- No Guild -]</nobr></td></tr>" & vbCrLf
                Else
                    html &= "<tr><td width=100%><nobr>[" & BiggestGuildName & "]</nobr></td></tr>" & vbCrLf
                End If
            Else
                html &= "<tr><td width=100%><nobr>[- Others -]</nobr></td></tr>" & vbCrLf
            End If

            For cl = 0 To Classes.Length - 1
                For p = 0 To PlayersCount - 1
                    guild = CharaInfo.GetCharactersInfo(Players(p)).Guild
                    If getClass(Players(p)) = Classes(cl) Then
                        If ((gld = 0) And (guild = BiggestGuildName)) Or ((gld = 1) And (guild <> BiggestGuildName)) Then
                            html &= "<tr><td width=100% class=""c_" & Classes(cl) & """>" & vbCrLf
                            html &= "<a href=""history_p" & p & ".html"" target=main>" & Players(p) & "</A><br/>" & vbCrLf
                            html &= "</td></tr>" & vbCrLf
                        End If
                    End If
                Next
            Next
        Next
        html &= "</table>" & vbCrLf
        html &= "</body>" & vbCrLf
        html &= "</html>" & vbCrLf

        Try
            FileOpen(1, My.Computer.FileSystem.CombinePath(TargetPath, "menu.html"), OpenMode.Output)
            Print(1, html)
        Catch ex As Exception

        End Try
        FileClose(1)

    End Sub

    Private Function GetHtmlHeader(ByVal Title As String) As String
        Dim CIV As New WowCrawler.CharaInfoViewer
        Return CIV.GetHtmlHeader(Title)
    End Function

    Private Sub EachRaidRanking()
        Const players As Integer = 100
        Dim TopDps(players) As Double
        Dim TopDpsName(players) As String
        Dim DummyDate(players) As Long

        Dim TopHeal(players) As Double
        Dim TopHealName(players) As String


        Dim i As Integer
        For i = 0 To players - 1
            TopDps(i) = 0
            TopDpsName(i) = ""
            TopHeal(i) = 0
            TopHealName(i) = ""

            DummyDate(i) = 0
        Next

        Dim name As String = ""
        Dim dpsrank As Integer = 0
        Dim healrank As Integer = 0

        Dim raid As Xml.XmlElement
        Dim player As Xml.XmlElement
        For Each raid In XmlDoc.SelectNodes("wws-history/raid")
            '--- get index of boss of raid
            Dim bossName As String
            Dim bossIdx As Integer = 0
            bossName = raid.Attributes("comment").Value
            Dim bs As Long
            For bs = 0 To boss.Length - 1
                If boss(bs) = bossName Then
                    bossIdx = bs
                    Exit For
                End If
            Next

            Dim ct As Integer = 0
            For Each player In raid.SelectNodes("player")
                Try
                    TopDps(ct) = player.Attributes("dmgout").Value
                Catch ex As Exception
                    TopDps(ct) = 0
                End Try
                Try
                    TopHeal(ct) = player.Attributes("heal").Value
                Catch ex As Exception
                    TopHeal(ct) = 0
                End Try
                name = player.Attributes("name").Value
                TopDpsName(ct) = name
                TopHealName(ct) = name

                '--- calculate average dps, hps, dispel for each boss
                Dim dps As Single = 0
                Dim hps As Single = 0
                Dim dspl As Single = 0
                Try
                    dps = player.Attributes("dmg").Value / player.ParentNode.Attributes("lg").Value * 60 * 1000
                Catch ex As Exception
                    dps = CDbl("0" & player.Attributes("dps").Value)
                End Try
                Try
                    hps = player.Attributes("effheal").Value / player.ParentNode.Attributes("lg").Value * 60 * 1000
                Catch ex As Exception
                    hps = CDbl("0" & player.Attributes("heal").Value)
                End Try
                Try
                    dspl = CInt(player.Attributes("decurse").Value)
                Catch ex As Exception
                    dspl = 0
                End Try
                For i = 0 To PlayersInfo.Length - 1
                    If PlayersInfo(i).Name = name Then
                        PlayersInfo(i).BossCombatInfo(bossIdx).BossName = bossName

                        If PlayersInfo(i).BossCombatInfo(bossIdx).Count > 0 Then
                            PlayersInfo(i).BossCombatInfo(bossIdx).AveDps *= (PlayersInfo(i).BossCombatInfo(bossIdx).Count / (PlayersInfo(i).BossCombatInfo(bossIdx).Count + 1))
                            PlayersInfo(i).BossCombatInfo(bossIdx).AveHps *= (PlayersInfo(i).BossCombatInfo(bossIdx).Count / (PlayersInfo(i).BossCombatInfo(bossIdx).Count + 1))
                            PlayersInfo(i).BossCombatInfo(bossIdx).AveDispel *= (PlayersInfo(i).BossCombatInfo(bossIdx).Count / (PlayersInfo(i).BossCombatInfo(bossIdx).Count + 1))
                        End If

                        PlayersInfo(i).BossCombatInfo(bossIdx).AveDps += dps / (PlayersInfo(i).BossCombatInfo(bossIdx).Count + 1)
                        PlayersInfo(i).BossCombatInfo(bossIdx).AveHps += hps / (PlayersInfo(i).BossCombatInfo(bossIdx).Count + 1)
                        PlayersInfo(i).BossCombatInfo(bossIdx).AveDispel += dspl / (PlayersInfo(i).BossCombatInfo(bossIdx).Count + 1)

                        PlayersInfo(i).BossCombatInfo(bossIdx).Count += 1

                        Exit For
                    End If
                Next

                ct += 1
            Next

            SortTop(TopDps, TopDpsName, DummyDate)
            SortTop(TopHeal, TopHealName, DummyDate)

            For Each player In raid.SelectNodes("player")
                name = player.Attributes("name").Value

                dpsrank = 0
                For i = 0 To players - 1
                    If TopDpsName(i) = name Then
                        If TopDps(i) = 0 Then
                            dpsrank = 0
                        Else
                            dpsrank = i + 1
                        End If
                        Exit For
                    End If
                Next

                healrank = 0
                For i = 0 To players - 1
                    If TopHealName(i) = name Then
                        If TopHeal(i) = 0 Then
                            healrank = 0
                        Else
                            healrank = i + 1
                        End If
                        Exit For
                    End If
                Next

                Dim rank As Xml.XmlAttribute

                rank = XmlDoc.CreateAttribute("dpsrank")
                rank.Value = dpsrank
                player.SetAttributeNode(rank)

                rank = XmlDoc.CreateAttribute("healrank")
                rank.Value = healrank
                player.SetAttributeNode(rank)

                '--- average rank for each boss
                For i = 0 To PlayersInfo.Length - 1
                    If PlayersInfo(i).Name = name Then
                        If dpsrank > 0 Then
                            PlayersInfo(i).BossCombatInfo(bossIdx).AveDpsRank *= (PlayersInfo(i).BossCombatInfo(bossIdx).DpsRankCount / (PlayersInfo(i).BossCombatInfo(bossIdx).DpsRankCount + 1))
                            PlayersInfo(i).BossCombatInfo(bossIdx).AveDpsRank += dpsrank / (PlayersInfo(i).BossCombatInfo(bossIdx).DpsRankCount + 1)
                            PlayersInfo(i).BossCombatInfo(bossIdx).DpsRankCount += 1
                        End If

                        If healrank > 0 Then
                            PlayersInfo(i).BossCombatInfo(bossIdx).AveHealRank *= (PlayersInfo(i).BossCombatInfo(bossIdx).HealRankCount / (PlayersInfo(i).BossCombatInfo(bossIdx).HealRankCount + 1))
                            PlayersInfo(i).BossCombatInfo(bossIdx).AveHealRank += healrank / (PlayersInfo(i).BossCombatInfo(bossIdx).HealRankCount + 1)
                            PlayersInfo(i).BossCombatInfo(bossIdx).HealRankCount += 1
                        End If

                        Exit For
                    End If
                Next
            Next
        Next

        '--- average value
        Dim dispel As Integer = 0
        Dim dead As Integer = 0

        For Each player In XmlDoc.SelectNodes("wws-history/raid[@latestNdays='1']/player")
            name = player.Attributes("name").Value

            For i = 0 To PlayersCount - 1
                If PlayersInfo(i).Name = name Then
                    dpsrank = player.Attributes("dpsrank").Value
                    healrank = player.Attributes("healrank").Value
                    dispel = player.Attributes("decurse").Value
                    dead = player.Attributes("death").Value
                    If dead > 1 Then dead = 1

                    If dpsrank = 1 Then
                        PlayersInfo(i).TopDpsCount += 1
                    End If

                    If healrank = 1 Then
                        PlayersInfo(i).TopHealCount += 1
                    End If

                    If dpsrank >= 1 Then
                        PlayersInfo(i).AveDpsRank = (PlayersInfo(i).AveDpsRank * PlayersInfo(i).AveDpsCount + dpsrank) / (PlayersInfo(i).AveDpsCount + 1)
                        PlayersInfo(i).AveDpsCount += 1
                    End If

                    If healrank >= 1 Then
                        PlayersInfo(i).AveHealRank = (PlayersInfo(i).AveHealRank * PlayersInfo(i).AveHealCount + healrank) / (PlayersInfo(i).AveHealCount + 1)
                        PlayersInfo(i).AveHealCount += 1
                    End If

                    PlayersInfo(i).AveDead = (PlayersInfo(i).AveDead * PlayersInfo(i).AveDeadCount + dead) / (PlayersInfo(i).AveDeadCount + 1)
                    PlayersInfo(i).AveDeadCount += 1

                    PlayersInfo(i).AveDispel = (PlayersInfo(i).AveDispel * PlayersInfo(i).AveDispelCount + dispel) / (PlayersInfo(i).AveDispelCount + 1)
                    PlayersInfo(i).AveDispelCount += 1

                    Exit For
                End If
            Next
        Next
    End Sub

    Private Function getCount(ByVal number As Integer) As String
        Dim c As String

        If number <= 0 Then
            c = "-"
        ElseIf number > 40 Then
            c = "-"
        Else
            Select Case number
                Case 1
                    c = "<B>" & Format(number) & "st" & "</B>"
                Case 2
                    c = Format(number) & "nd"
                Case 3
                    c = Format(number) & "rd"
                Case 21
                    c = Format(number) & "st"
                Case 22
                    c = Format(number) & "nd"
                Case 23
                    c = Format(number) & "rd"
                Case 31
                    c = Format(number) & "st"
                Case 32
                    c = Format(number) & "nd"
                Case 33
                    c = Format(number) & "rd"
                Case Else
                    c = Format(number) & "th"
            End Select
        End If

        Return c
    End Function


    Private Sub CreateTop10Html()
        Dim html As String = ""
        Dim bnode As Xml.XmlElement
        Dim node As Xml.XmlElement
        Dim i As Integer
        '-----
        Dim TopDps(Top_N_Count) As Double
        Dim TopDpsName(Top_N_Count) As String
        Dim TopDpsDate(Top_N_Count) As Long

        Dim TopHeal(Top_N_Count) As Double
        Dim TopHealName(Top_N_Count) As String
        Dim TopHealDate(Top_N_Count) As Long

        Dim dps As Double = 0
        Dim heal As Double = 0
        Dim raiddate As Long = 0
        Dim name As String = ""


        html = GetHtmlHeader("Top " & Top_N_Count & " Players")

        html &= "<P>Updated: " & Format(Today(), "MM-dd-yyyy") & ", DON'T BUY GOLD!</P>"

        Dim b As Integer
        If boss IsNot Nothing Then
            For b = 0 To boss.Length - 1
                For i = 0 To Top_N_Count - 1
                    TopDps(i) = 0
                    TopDpsName(i) = ""
                    TopDpsDate(i) = 0

                    TopHeal(i) = 0
                    TopHealName(i) = ""
                    TopHealDate(i) = 0
                Next

                'For Each bnode In XmlDoc.SelectNodes("wws-history/raid[@comment=""" & boss(b) & """][@latestNdays=""1""]")
                For Each bnode In XmlDoc.SelectNodes("wws-history/raid[@comment=""" & boss(b) & """]")
                    For Each node In bnode.SelectNodes("player")
                        name = node.Attributes("name").Value
                        raiddate = node.ParentNode.Attributes("start").Value

                        If node.ParentNode.Attributes("lg").Value = 0 Then
                            dps = 0
                            heal = 0
                        Else
                            Try
                                dps = node.Attributes("dmg").Value / node.ParentNode.Attributes("lg").Value * 60 * 1000
                            Catch ex As Exception
                                dps = CDbl(node.Attributes("dps").Value)
                            End Try

                            Try
                                heal = node.Attributes("effheal").Value / node.ParentNode.Attributes("lg").Value * 60 * 1000
                            Catch ex As Exception
                                heal = CDbl(node.Attributes("heal").Value)
                            End Try
                        End If

                        TopDps(Top_N_Count) = dps
                        TopDpsName(Top_N_Count) = name
                        TopDpsDate(Top_N_Count) = raiddate
                        SortTop(TopDps, TopDpsName, TopDpsDate)

                        TopHeal(Top_N_Count) = heal
                        TopHealName(Top_N_Count) = name
                        TopHealDate(Top_N_Count) = raiddate
                        SortTop(TopHeal, TopHealName, TopHealDate)
                    Next
                Next

                html &= vbCrLf
                html &= "<h2 onclick=expand('boss" & b & "')>" & boss(b) & "/" & getZone(boss(b)) & "</h2>" & vbCrLf
                html &= "<div id=boss" & b & ">" & vbCrLf

                html &= "<table><tr><td valign=top>" & vbCrLf

                Dim percent As Double
                '--- dps
                html &= "<table border><tr bgcolor=pink><th>Rank</th><th>Player</th><th colspan=2>DPS</th><th>Date</th></tr>" & vbCrLf
                For i = 0 To Top_N_Count - 1
                    If TopDps(i) = 0 Or TopDpsName(i) = "" Then
                    Else
                        html &= "<tr>"
                        html &= "<th bgcolor=pink>" & i + 1 & "</th>"
                        html &= "<td class=""c_" & getClass(TopDpsName(i)) & """>" & TopDpsName(i) & "</td>"
                        percent = Math.Round(TopDps(i) / TopDps(0) * 100, 0)
                        html &= GetBar(percent, "red")
                        html &= "<td align=right>" & Format(TopDps(i), "###,###,##0.0") & "</td>"
                        html &= "<td>" & GetDate(TopDpsDate(i)) & "</td>"
                        html &= "</tr>" & vbCrLf
                    End If
                Next
                html &= "</table>" & vbCrLf

                html &= "</td><td valign=top>" & vbCrLf
                '--- hps
                html &= "<table border><tr bgcolor=skyblue><th>Rank</th><th>Player</th><th colspan=2>EffHPS</th><th>Date</th></tr>" & vbCrLf
                For i = 0 To Top_N_Count - 1
                    If TopHeal(i) = 0 Or TopHealName(i) = "" Then
                    Else
                        html &= "<tr>"
                        html &= "<th bgcolor=skyblue>" & i + 1 & "</th>"
                        html &= "<td class=""c_" & getClass(TopHealName(i)) & """>" & TopHealName(i) & "</td>"

                        Try
                            percent = Math.Round(TopHeal(i) / TopHeal(0) * 100, 0)
                        Catch ex As Exception
                            percent = 0
                        End Try
                        html &= GetBar(percent, "blue")
                        html &= "<td align=right>" & Format(TopHeal(i), "###,###,##0.0") & "</td>"
                        html &= "<td>" & GetDate(TopHealDate(i)) & "</td>"
                        html &= "</tr>" & vbCrLf
                    End If
                Next
                html &= "</table>" & vbCrLf

                html &= "</td></tr></table>" & vbCrLf
                html &= "</div>" & vbCrLf
            Next
        End If

        html &= "</body>" & vbCrLf
        html &= "</html>" & vbCrLf

        Try
            FileOpen(1, My.Computer.FileSystem.CombinePath(TargetPath, "top10.html"), OpenMode.Output)
            Print(1, html)
        Catch ex As Exception

        End Try
        FileClose(1)

        '-----
    End Sub

    Private Sub CreateTopAve10Html()
        Dim html As String = ""
        Dim i As Integer
        Dim ct As Integer

        '-----
        Dim Rank(PlayersCount - 1) As Double

        html = GetHtmlHeader("Misc ranking / latest " & Latest_N_Days & " days")

        html &= "<P>Updated: " & Format(Today(), "MM-dd-yyyy") & ", DON'T BUY GOLD!</P>"


        '--- Dispel
        Dim cp As New CompareDoubleDescend
        For i = 0 To PlayersCount - 1
            Rank(i) = PlayersInfo(i).AveDispel
        Next
        Array.Sort(Rank, PlayersInfo, cp)

        html &= "<h2 onclick=expand('ave10dispel')>Average Dispel</h2>" & vbCrLf
        html &= "<div id=ave10dispel>"

        html &= "<table border><tr><th>Rank</th><th>Player</th><th colspan=2>Average #Dispel</th><th>#Count</th></tr>" & vbCrLf
        ct = 1
        Dim maxdispel As Double = 0
        For i = 0 To PlayersCount - 1
            If PlayersInfo(i).AveDispel = 0 Then
                Exit For
            End If

            If PlayersInfo(i).AveDispelCount >= 10 Then

                If ct = 1 Then
                    maxdispel = PlayersInfo(i).AveDispel
                End If

                html &= "<tr>"
                html &= "<th>" & ct & "</th>"
                html &= "<td class=""c_" & getClass(PlayersInfo(i).Name) & """>" & PlayersInfo(i).Name & "</td>"
                html &= GetBar(PlayersInfo(i).AveDispel / maxdispel * 100, "purple")
                html &= "<td align=right>" & Format(PlayersInfo(i).AveDispel, "#,##0.00") & "</td>"
                html &= "<td align=right>" & Format(PlayersInfo(i).AveDispelCount, "#,##0") & "</td>"
                html &= "</tr>" & vbCrLf

                ct += 1
            End If

            If ct > Top_N_Count Then
                Exit For
            End If
        Next
        html &= "</table>" & vbCrLf
        html &= "</div>" & vbCrLf

        '--- DPS
        For i = 0 To PlayersCount - 1
            Rank(i) = PlayersInfo(i).AveDpsRank
        Next
        Array.Sort(Rank, PlayersInfo)

        html &= vbCrLf
        html &= "<h2 onclick=expand('ave10dps')>Average DPS Rank </h2>" & vbCrLf
        html &= "<div id=ave10dps>" & vbCrLf

        html &= "<table border><tr bgcolor=pink><th>Rank</th><th>Player</th><th colspan=2>Average rank</th><th>#Top</th><th>#Count</th></tr>" & vbCrLf
        ct = 1

        Dim max As Single = 0
        Dim min As Single = PlayersCount
        For i = 0 To PlayersCount - 1
            If PlayersInfo(i).AveDpsCount >= 10 Then
                If PlayersInfo(i).AveDpsRank > max Then
                    max = PlayersInfo(i).AveDpsRank
                End If
                If PlayersInfo(i).AveDpsRank < min Then
                    min = PlayersInfo(i).AveDpsRank
                End If
            End If
            If max = min Then
                max = min + 1
            End If
        Next
        For i = 0 To PlayersCount - 1
            If PlayersInfo(i).AveDpsCount >= 10 Then
                html &= "<tr>"
                html &= "<th bgcolor=pink>" & ct & "</th>"
                html &= "<td class=""c_" & getClass(PlayersInfo(i).Name) & """>" & PlayersInfo(i).Name & "</td>"
                html &= GetBar((max - PlayersInfo(i).AveDpsRank) / (max - min) * 100, "red")
                html &= "<td align=right>" & Format(PlayersInfo(i).AveDpsRank, "#,##0.00") & "</td>"
                html &= "<td align=right>" & Format(PlayersInfo(i).TopDpsCount, "#,##0") & "</td>"
                html &= "<td align=right>" & Format(PlayersInfo(i).AveDpsCount, "#,##0") & "</td>"
                html &= "</tr>" & vbCrLf

                ct += 1
            End If

            If ct > Top_N_Count Then
                Exit For
            End If
        Next
        html &= "</table>" & vbCrLf
        html &= "</div>" & vbCrLf

        '--- Heal
        For i = 0 To PlayersCount - 1
            Rank(i) = PlayersInfo(i).AveHealRank
        Next
        Array.Sort(Rank, PlayersInfo)

        html &= vbCrLf
        html &= "<h2 onclick=expand('ave10heal')>Average Healing Rank </h2>" & vbCrLf
        html &= "<div id=ave10heal>" & vbCrLf

        html &= "<table border><tr bgcolor=skyblue><th>Rank</th><th>Player</th><th colspan=2>Average rank</th><th>#Top</th><th>#Count</th></tr>" & vbCrLf
        ct = 1

        max = 0
        min = PlayersCount
        For i = 0 To PlayersCount - 1
            If PlayersInfo(i).AveHealCount >= 10 Then
                If PlayersInfo(i).AveHealRank > max Then
                    max = PlayersInfo(i).AveHealRank
                End If
                If PlayersInfo(i).AveHealRank < min Then
                    min = PlayersInfo(i).AveHealRank
                End If
            End If
            If max = min Then
                max = min + 1
            End If
        Next

        For i = 0 To PlayersCount - 1
            If PlayersInfo(i).AveHealCount >= 10 Then
                html &= "<tr>"
                html &= "<th bgcolor=skyblue>" & ct & "</th>"
                html &= "<td class=""c_" & getClass(PlayersInfo(i).Name) & """>" & PlayersInfo(i).Name & "</td>"
                html &= GetBar((max - PlayersInfo(i).AveHealRank) / (max - min) * 100, "blue")
                html &= "<td align=right>" & Format(PlayersInfo(i).AveHealRank, "#,##0.00") & "</td>"
                html &= "<td align=right>" & Format(PlayersInfo(i).TopHealCount, "#,##0") & "</td>"
                html &= "<td align=right>" & Format(PlayersInfo(i).AveHealCount, "#,##0") & "</td>"
                html &= "</tr>" & vbCrLf

                ct += 1
            End If

            If ct > Top_N_Count Then
                Exit For
            End If
        Next
        html &= "</table>" & vbCrLf
        html &= "</div>" & vbCrLf

        '---
        html &= "</body>" & vbCrLf
        html &= "</html>" & vbCrLf

        Try
            FileOpen(1, My.Computer.FileSystem.CombinePath(TargetPath, "topave.html"), OpenMode.Output)
            Print(1, html)
        Catch ex As Exception

        End Try
        FileClose(1)

        '-----
    End Sub

    Private Function SortTop(ByRef value As Double(), ByRef name As String(), ByRef raiddate As Long()) As Boolean
        Dim i As Integer
        Dim j As Integer

        Dim v As Double
        Dim n As String
        Dim d As Long

        For i = 0 To name.Length - 2
            If name(i) = name(name.Length - 1) Then
                If value(i) < value(name.Length - 1) Then
                    value(i) = value(name.Length - 1)
                    raiddate(i) = raiddate(name.Length - 1)
                End If
                value(name.Length - 1) = 0
            End If
        Next

        For i = 0 To value.Length - 2
            For j = i + 1 To value.Length - 1
                If value(i) < value(j) Then
                    v = value(i)
                    value(i) = value(j)
                    value(j) = v

                    n = name(i)
                    name(i) = name(j)
                    name(j) = n

                    d = raiddate(i)
                    raiddate(i) = raiddate(j)
                    raiddate(j) = d
                End If
            Next
        Next

        Return True
    End Function

    Private Function getClass(ByVal name As String) As String
        Dim node As Xml.XmlElement = Nothing

        For Each node In XmlDoc.SelectNodes("wws-history/raid/player")
            If node.Attributes("name").Value = name Then
                Return node.Attributes("classe").Value
            End If
        Next

        Return Classes(Classes.Length - 1)
    End Function

    Private Function getZone(ByVal boss As String) As String
        Dim node As Xml.XmlElement = Nothing

        For Each node In XmlDoc.SelectNodes("wws-history/raid")
            If node.Attributes("comment").Value = boss Then
                Return node.Attributes("zone").Value
            End If
        Next

        Return Classes("unknown")
    End Function

    Private Function GetBar(ByVal percent As Double, ByVal colour As String) As String
        Dim pc As Integer

        Try
            pc = Math.Round(percent, 0, MidpointRounding.ToEven)
        Catch ex As Exception
            pc = 0
        End Try

        Dim html As String = ""

        If pc <= 0 Then
            html &= "<td><table width=100px><tr><td></td><td width=100% height=8px></td></tr></table></td>"
        ElseIf pc >= 100 Then
            html &= "<td><table width=100px><tr><td bgcolor=" & colour & " width=100% height=8px></td><td></td></tr></table></td>"
        Else
            html &= "<td><table width=100px><tr><td bgcolor=" & colour & " width=" & pc & "% height=8px></td><td width=" & 100 - pc & "%></td></tr></table></td>"
        End If

        Return html
    End Function

    Private Sub RemoveFiles()
        Dim parent As String
        parent = My.Computer.FileSystem.CombinePath(TargetPath, "..\")

        Dim folder As String
        Dim file As String

        Dim datespan As Long = 0

        For Each folder In My.Computer.FileSystem.GetDirectories(parent)
            If InStr(LCase(folder), "\sws-") Then
                Dim i As Integer
                Dim ds As String = ""
                For i = Len(folder) To 1 Step -1
                    If InStr("0123456789", Mid(folder, i, 1)) Then
                        ds = Mid(folder, i, 1) & ds
                    Else
                        datespan = (Today - CalculateDate(CLng("0" & ds) * 1000)).Days
                        Exit For
                    End If
                Next

                'remove descriptions
                If RemoveDescriptionsDateSpan >= 0 And RemoveDescriptionsDateSpan <= datespan Then
                    For Each file In My.Computer.FileSystem.GetFiles(folder)
                        If InStr(LCase(file), "\spell_") Or InStr(LCase(file), "\group_") Or InStr(LCase(file), "\actor_0xf") Or InStr(LCase(file), ".json") Then
                            My.Computer.FileSystem.DeleteFile(file)
                        Else
                            '
                        End If
                    Next
                End If

                'remove full
                If RemoveFullDateSpan >= 0 And RemoveFullDateSpan <= datespan Then
                    For Each file In My.Computer.FileSystem.GetFiles(folder)
                        If InStr(LCase(file), "\index.html") Or InStr(LCase(file), "\data.xml") Then
                            '
                        Else
                            My.Computer.FileSystem.DeleteFile(file)
                        End If
                    Next
                End If
            End If
        Next
    End Sub
End Module


#Region "Raid Bosses"
Public Class RaidBossList
    Private Const XmlFileName As String = "RaidBosses.xml"

    Public Structure Bosses
        Dim Packages() As Package
    End Structure

    Public Structure Package
        <XmlAttribute()> Dim name As String
        Dim Areas() As Area
    End Structure

    Public Structure Area
        <XmlAttribute()> Dim code As String
        <XmlAttribute()> Dim name As String
        <XmlAttribute()> Dim min_lv As Integer
        <XmlAttribute()> Dim max_lv As Integer
        <XmlAttribute()> Dim man As Integer
        Dim Bosses() As Boss
    End Structure

    Public Structure Boss
        <XmlAttribute()> Dim name As String
    End Structure

    Public RaidBosses As Bosses

    Public Function CreateNewBoss(ByVal name As String) As Boss
        Dim b As New Boss
        b.name = name
        Return b
    End Function

    Public Sub New()
        Dim Boss As New Boss
        Dim Area As New Area
        Dim package As New Package
        RaidBosses = New Bosses

        Boss.name = "unknown"

        Area.code = "unknown"
        Area.name = "unknown"
        Area.min_lv = 1
        Area.max_lv = 999
        Area.man = 40
        ReDim Area.Bosses(0)
        Area.Bosses(0) = Boss

        package.name = "unknown"
        ReDim package.Areas(0)
        package.Areas(0) = Area

        ReDim RaidBosses.Packages(0)
        RaidBosses.Packages(0) = package

        Dim xu As New XmlUtils.AccessXml
        Dim pass As String = My.Computer.FileSystem.SpecialDirectories.AllUsersApplicationData.ToString
        xu.ImportFromXml(RaidBosses, My.Computer.FileSystem.CombinePath(pass, XmlFileName))
    End Sub

    Protected Overrides Sub Finalize()
        Dim xu As New XmlUtils.AccessXml
        Dim pass As String = My.Computer.FileSystem.SpecialDirectories.AllUsersApplicationData.ToString
        '        xu.ExportByXml(RaidBosses, My.Computer.FileSystem.CombinePath(pass, XmlFileName))

        MyBase.Finalize()
    End Sub

    Public Function GetBossCode(ByVal Boss As String) As Double
        Dim pn As Integer = 0
        Dim an As Integer = 0
        Dim bn As Integer = 0

        Dim b As Long = -1

        If RaidBosses.Packages IsNot Nothing Then
            For pn = 0 To RaidBosses.Packages.Length - 1
                If RaidBosses.Packages(pn).Areas IsNot Nothing Then
                    For an = 0 To RaidBosses.Packages(pn).Areas.Length - 1
                        If RaidBosses.Packages(pn).Areas(an).Bosses IsNot Nothing Then
                            For bn = 0 To RaidBosses.Packages(pn).Areas(an).Bosses.Length - 1
                                If RaidBosses.Packages(pn).Areas(an).Bosses(bn).name = Boss Then
                                    If LCase(RaidBosses.Packages(pn).name) = "ignore" Then
                                        b = -1
                                    Else
                                        b = pn * 1000 ^ 2 + an * 1000 + bn
                                    End If
                                    Return b
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        End If

        Try
            Dim l As Integer
            l = RaidBosses.Packages(0).Areas(0).Bosses.Length
            ReDim Preserve RaidBosses.Packages(0).Areas(0).Bosses(l)
            RaidBosses.Packages(0).Areas(0).Bosses(l) = CreateNewBoss(Boss)
        Catch ex As Exception

        End Try

        Return b
    End Function

    Public Function GetAreaName(ByVal Boss As String) As String
        Dim pn As Integer = 0
        Dim an As Integer = 0
        Dim bn As Integer = 0

        Dim areacode As String = ""

        If RaidBosses.Packages IsNot Nothing Then
            For pn = 0 To RaidBosses.Packages.Length - 1
                If RaidBosses.Packages(pn).Areas IsNot Nothing Then
                    For an = 0 To RaidBosses.Packages(pn).Areas.Length - 1
                        If RaidBosses.Packages(pn).Areas(an).Bosses IsNot Nothing Then
                            For bn = 0 To RaidBosses.Packages(pn).Areas(an).Bosses.Length - 1
                                If RaidBosses.Packages(pn).Areas(an).Bosses(bn).name = Boss Then
                                    If LCase(RaidBosses.Packages(pn).name) = "ignore" Then
                                        areacode = ""
                                    ElseIf LCase(RaidBosses.Packages(pn).name) = "General" Then
                                        areacode = ""
                                    Else
                                        areacode = RaidBosses.Packages(pn).Areas(an).code
                                    End If
                                    Return areacode
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        End If

        Return areacode
    End Function

End Class

Public Class BossCompare
    Implements IComparer

    Private Bosses As New RaidBossList

    Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare

        Dim d1 As String = CType(x, String)
        Dim d2 As String = CType(y, String)

        Dim c1 As Double = Bosses.GetBossCode(d1)
        Dim c2 As Double = Bosses.GetBossCode(d2)

        If c1 > c2 Then
            Return -1
        ElseIf c1 < c2 Then
            Return 1
        ElseIf d1 > d2 Then
            Return -1
        ElseIf d1 < d2 Then
            Return 1
        Else
            Return 0
        End If
    End Function

End Class
#End Region

